package com.zhongli.devplatform.controller.common;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zhongli.devplatform.bean.Res;
import com.zhongli.devplatform.bean.SecurityHelper;
import com.zhongli.devplatform.constant.Consts;
import com.zhongli.devplatform.dto.ErrorRateDto;
import com.zhongli.devplatform.po.common.ReadClazzOperationPO;
import com.zhongli.devplatform.po.common.ReadClazzPO;
import com.zhongli.devplatform.po.live.ReadWatchHistoryPO;
import com.zhongli.devplatform.po.sys.*;
import com.zhongli.devplatform.po.teacher.ReadOperationPO;
import com.zhongli.devplatform.po.user.ReadUserPO;
import com.zhongli.devplatform.po.user.ReadUserParentPO;
import com.zhongli.devplatform.service.imp.common.ReadClazzOperationService;
import com.zhongli.devplatform.service.imp.common.ReadClazzService;
import com.zhongli.devplatform.service.imp.live.ReadWatchHistoryService;
import com.zhongli.devplatform.service.imp.student.ReadUserParentService;
import com.zhongli.devplatform.service.imp.sys.*;
import com.zhongli.devplatform.service.imp.teacher.ReadOperationService;
import com.zhongli.devplatform.service.imp.user.ReadUserService;
import com.zhongli.devplatform.utils.BeanCopierUtil;
import com.zhongli.devplatform.utils.user.UserUtil;
import com.zhongli.devplatform.vo.common.LearningProVO;
import com.zhongli.devplatform.vo.sys.ErrorRateVo;
import com.zhongli.devplatform.vo.sys.ReadVideoWatchVO;
import com.zhongli.devplatform.vo.sys.SubjectVO;
import com.zhongli.devplatform.vo.sys.TopicCorrectRateVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author wy
 * @date 2020/8/4
 */
@Api(tags = "学习详情报表", description = "学习详情报表", value = "学习详情报表")
@RestController
@RequestMapping("/studyReportDetails")
public class ReportDetailsController {

    @Autowired
    private ReadUserService userService;

    @Autowired
    private ReadUserParentService userParentService;

    @Autowired
    private ReadClazzService clazzService;

    @Autowired
    private ReadChapterExercisesService chapterExercisesService;

    @Autowired
    private ReadWatchHistoryService watchHistoryService;

    @Autowired
    private ReadVideoService videoService;

    @Autowired
    private ReadChapterService chapterService;

    @Autowired
    private ReadKnowledgePointService knowledgePointService;

    @Autowired
    private ReadOperationService operationService;

    @Autowired
    private ReadClazzOperationService clazzOperationService;

    @Autowired
    private ReadSubjectService subjectService;


    /**
     *  根据所选学生id 获取学习情况统计报表 老师端
     * @param errorRateDto  学生id {@link ErrorRateDto}
     * @return 报表信息
     */
    @ApiOperation("根据所选学生id 获取学习情况统计报表---答题正确率 --- 老师端/家长端 Integer studentId; String groupByType ; Integer subjectId;")
    @GetMapping("/correctRate")
    public Res<HashMap<String, List<String>>> studyReportOfErrorRate(@ModelAttribute ErrorRateDto errorRateDto){
        HashMap<String, List<String>> result = new LinkedHashMap<>();
        ArrayList<String> categories = new ArrayList<>();
        ArrayList<String> data = new ArrayList<>();
        if (errorRateDto.getParentId() != null){
            ReadUserParentPO userParentPO = userParentService.getOne(new QueryWrapper<ReadUserParentPO>()
                    .eq("parent_id",errorRateDto.getParentId()));
            if (userParentPO == null){
                result.put("categories",categories);
                result.put("data",data);
                return Res.ok(result);
            }
            errorRateDto.setStudentId(userParentPO.getUserId());
        }
        //ReadUserPO byId = userService.getById(errorRateDto.getStudentId());
        //ReadClazzPO clazzPO = clazzService.getById(byId.getClazzId());
        //errorRateDto.setGradeId(clazzPO.getGradeId());
        List<ErrorRateVo> dataList = chapterExercisesService.studyReportCorrectRate(errorRateDto);


        dataList.forEach(item -> {
            categories.add(item.getXGroupBy());
            data.add(item.getYErrorRate());
        });
        Collections.reverse(categories);
        Collections.reverse(data);
        result.put("categories",categories);
        result.put("data",data);
        return Res.ok(result);
    }

    /**
     *  根据所选学生id 获取学习情况统计报表 习题正确率 老师端
     * @param errorRateDto  学生id {@link ErrorRateDto}
     * @return 报表信息
     */
    @ApiOperation("根据所选学生id 获取学习情况统计报表---习题正确率 --- 老师端 参数 Integer studentId; Integer subjectId;")
    @GetMapping("/AllTopicCorrectRate")
    public Res studyReportOfAllTopicCorrectRate(@ModelAttribute ErrorRateDto errorRateDto){
        if (errorRateDto.getParentId() != null){
            ReadUserParentPO userParentPO = userParentService.getOne(new QueryWrapper<ReadUserParentPO>()
                    .eq("parent_id",errorRateDto.getParentId()));
            if (userParentPO == null)  return Res.ok(new TopicCorrectRateVo());
            errorRateDto.setStudentId(userParentPO.getUserId());
        }
        //ReadUserPO byId = userService.getById(errorRateDto.getStudentId());
        //if (byId == null) {
        //    return Res.ok(new TopicCorrectRateVo());
        //}
        //ReadClazzPO clazzPO = clazzService.getById(byId.getClazzId());
        //errorRateDto.setGradeId(clazzPO.getGradeId());
        TopicCorrectRateVo data = chapterExercisesService.studyReportOfAllTopicCorrectRate(errorRateDto);
        return Res.ok(data);
    }


    /**
     *  根据所选学生id 获取学习情况统计报表 视频观看次数 老师端
     * @param errorRateDto  学生id {@link ErrorRateDto}
     * @return 报表信息
     */
    @ApiOperation("根据所选学生id 获取学习情况统计报表---视频观看次数 --- 老师端/家长端 Integer studentId; Integer subjectId;")
    @GetMapping("/videoWatchCount")
    public Res studyReportOfWatchCount(@ModelAttribute ErrorRateDto errorRateDto){
        HashMap<String, Object> result = new LinkedHashMap<>();
        ArrayList<String> categories = new ArrayList<>();
        ArrayList<Integer> data = new ArrayList<>();
        if (errorRateDto.getParentId() != null){
            ReadUserParentPO userParentPO = userParentService.getOne(new QueryWrapper<ReadUserParentPO>()
                    .eq("parent_id",errorRateDto.getParentId()));
            if (userParentPO == null)  return Res.ok(result);
            errorRateDto.setStudentId(userParentPO.getUserId());
        }
        List<ReadVideoWatchVO> dataList = watchHistoryService.studyReportOfWatchCount(errorRateDto);
        dataList.forEach(item -> {
            categories.add(item.getXGroupBy());
            data.add(item.getYWatchCount());
        });
        Collections.reverse(categories);
        Collections.reverse(data);
        result.put("categories",categories);
        result.put("data",data);
        return Res.ok(result);
    }



    /**
     *  根据所选学生id 获取学习情况统计报表 视频观看进度 老师端/学生端
     * @param errorRateDto  学生id {@link ErrorRateDto}
     * @return 报表信息
     */
    @ApiOperation("根据所选学生id 获取学习情况统计报表---视频观看进度 --- 老师端/学生端 参数 Integer studentId; Integer subjectId;")
    @GetMapping("/videoWatchSchedule")
    public Res videoWatchSchedule(@ModelAttribute ErrorRateDto errorRateDto){
        Map<String, Integer> result = new HashMap<>();//根据key排序
        result.put("total",0);
        result.put("watchedCount",0);
        AtomicInteger watchedCount = new AtomicInteger();

        if (errorRateDto.getParentId() != null){
            ReadUserParentPO userParentPO = userParentService.getOne(new QueryWrapper<ReadUserParentPO>()
                    .eq("parent_id",errorRateDto.getParentId()));
            if (userParentPO == null)  return Res.ok(result);
            errorRateDto.setStudentId(userParentPO.getUserId());
        }
        List<ReadWatchHistoryPO> userHistoryPO = watchHistoryService.list(new QueryWrapper<ReadWatchHistoryPO>()
                .eq("user_id", errorRateDto.getStudentId()));

        List<ReadVideoPO> videoWatched = null;
        if (!userHistoryPO.isEmpty()){
            List<Integer> videoIds = userHistoryPO.stream()
                    .map(ReadWatchHistoryPO::getVideoId)
                    .collect(Collectors.toList());
            videoWatched = videoService.list(new QueryWrapper<ReadVideoPO>()
                    .eq("subject_id",errorRateDto.getSubjectId())
                    .eq("video_type",Consts.VIDEO_TYPE_KNOWLEDGE)
                    .in("id",videoIds));
        }

        ReadUserPO byId = userService.getById(errorRateDto.getStudentId());
        ReadClazzPO clazzPO = clazzService.getById(byId.getClazzId());
        List<ReadChapterPO> list = chapterService.list(new QueryWrapper<ReadChapterPO>()
                .eq("grade_id", clazzPO.getGradeId())
                .eq("subject_id", errorRateDto.getSubjectId()));
                //.eq("class_id", clazzPO.getId()));
        if (list.isEmpty()) return Res.ok(result);
        List<Integer> chapterIds = list.stream()
                .map(ReadChapterPO::getId)
                .collect(Collectors.toList());
        List<ReadKnowledgePointPO> knowledgePointPOS = knowledgePointService.list(new QueryWrapper<ReadKnowledgePointPO>()
                .in("chapter_id", chapterIds));

        Map<Integer, List<ReadKnowledgePointPO>> listMap = knowledgePointPOS
                .stream()
                .collect(Collectors.groupingBy(ReadKnowledgePointPO::getChapterId));

        Set<Map.Entry<Integer, List<ReadKnowledgePointPO>>> entries = listMap.entrySet();

        List<ReadVideoPO> finalVideoWatched = videoWatched;
        if (finalVideoWatched == null){
            result.put("total",listMap.isEmpty()?0:listMap.size());
            result.put("watchedCount",watchedCount.get());
            return Res.ok(result);
        }
        entries.forEach(item->{ //每个章节下的知识点对应的视频 包含在已看完的视频中表示已经 看完怎个章节
            List<ReadKnowledgePointPO> value = item.getValue();
            List<Integer> collect = value.stream()
                    .map(ReadKnowledgePointPO::getId).collect(Collectors.toList());
            List<ReadVideoPO> AllVideos = videoService.list(new QueryWrapper<ReadVideoPO>()
                    .in("resources_id", collect));
            boolean isFishedChapter = finalVideoWatched.containsAll(AllVideos);
            if (isFishedChapter) watchedCount.getAndIncrement();
        });
        result.put("total",listMap.isEmpty()?0:listMap.size());
        result.put("watchedCount",watchedCount.get());

        return Res.ok(result);
    }

    /**
     * 查询学生是否以全部的作业
     *  @return 结果集
     */
    @ApiOperation("获取当前学生的的所有作业")
    @GetMapping("/currentStudentAllOpera")
    public Res getCurrentStuOperation(){
        Integer currentUserId = SecurityHelper.getCurrentUserId();
        ReadUserPO userPO = userService.getById(currentUserId);
        List<ReadClazzOperationPO> list =
                clazzOperationService.list(new QueryWrapper<ReadClazzOperationPO>().eq("clazz_id", userPO.getClazzId()));
        List<Integer> operationIds = list
                .stream()
                .map(ReadClazzOperationPO::getOperationId)
                .collect(Collectors.toList());
        List<ReadOperationPO> data = operationService.listByIds(operationIds);
        return Res.ok(data);
    }


    /**
     * 当前家长获取 自己孩子的学习进度 家长端
     *  @return 结果集
     */
    @ApiOperation("当前家长获取 自己孩子的学习进度 家长端 --- subjectId parentId")
    @GetMapping("/currentLearningProgress")
    public Res<Map<String, List<LearningProVO>>> getCurrentLearningProgress(@ModelAttribute ErrorRateDto errorRateDto){
        ReadUserParentPO userParentPO = userParentService.getOne(new QueryWrapper<ReadUserParentPO>()
                .eq("parent_id",errorRateDto.getParentId()));
        errorRateDto.setStudentId(userParentPO.getUserId());//查询到当前家长的学生id
        ReadUserPO userPO = userService.getById(errorRateDto.getStudentId());
        ReadClazzPO clazzPO = clazzService.getById(userPO.getClazzId());
        errorRateDto.setGradeId(clazzPO.getGradeId());
        List<ReadChapterPO> list = chapterService.list(new QueryWrapper<ReadChapterPO>()//查询当前学生的章节信息
                .eq("grade_id", clazzPO.getGradeId())
                .eq("subject_id", errorRateDto.getSubjectId()));
                //.eq("class_id", clazzPO.getId()));
        List<Integer> chapterIds = list.stream().map(ReadChapterPO::getId).collect(Collectors.toList());
        List<ReadKnowledgePointPO> knowledgePoints = knowledgePointService
                .list(new QueryWrapper<ReadKnowledgePointPO>()
                        .in("chapter_id", chapterIds));
        Map<Integer, List<ReadKnowledgePointPO>> listMap = knowledgePoints
                            .stream()
                            .collect(Collectors.groupingBy(ReadKnowledgePointPO::getChapterId));

        //已经完成了的知识点
        List<ReadChapterExercisesPO> fished = chapterExercisesService
                .list(new QueryWrapper<ReadChapterExercisesPO>().eq("student_id", userParentPO.getUserId()));
        List<Integer> fishedIds = fished.stream().map(ReadChapterExercisesPO::getKnowledgeId).collect(Collectors.toList());

        Map<String, List<LearningProVO>> result = new TreeMap<>(String::compareTo);//根据key排序
        listMap.forEach((key, value) -> { //每个章节下的知识点对应的视频 包含在已看完的视频中表示已经 看完怎个章节
            value.forEach(item -> {
                LearningProVO learningProVO = new LearningProVO();
                learningProVO.setKnowledgeId(item.getId());
                learningProVO.setKnowledgeName(item.getKnowledgeName());
                learningProVO.setFished(fishedIds.contains(item.getId()));
                ArrayList<LearningProVO> data = new ArrayList<>();
                data.add(learningProVO);
                result.put(chapterService.getById(key).getChapterTitle(), data);
            });
        });
        return Res.ok(result);
    }


    @ApiOperation("老师端获取 学习进度雷达图 --- subjectId")
    @GetMapping("/radarChart/{studentId}")
    public Res radarChart(@ApiParam(value = "老师必须传递学生id")
                              @PathVariable Integer studentId){
        if (studentId == -1){
            String userRole = UserUtil.getUserRole();
            Integer currentStu = SecurityHelper.getCurrentUserId();
            if("parent".equals(userRole)){
                ReadUserParentPO userParentPO = userParentService.getOne(new QueryWrapper<ReadUserParentPO>()
                        .eq("parent_id",currentStu));
                studentId = userParentPO.getUserId();
            }
        }
        //获取当前学生的所在年级的科目
        List<ReadSubjectPO> subjects = subjectService.getStudentSubject(studentId);
        List<SubjectVO> subjectVOs = BeanCopierUtil.copy(subjects, SubjectVO.class);
        //学生---学习进度雷达图
        List<Integer> values = userService.radarChart(studentId,subjectVOs);
        HashMap<String, Object> result = new HashMap<>();
        result.put("subject",subjectVOs);
        result.put("values",values);
        return Res.ok(result);
    }
}
